import {useState,useCallback} from 'react'
import MemoChildA from './MemoChildA'
import MemoChildB from './MemoChildB'
import MemoChildC from './MemoChildC'
import MemoChildD from './MemoChildD'
import {Button,Divider} from 'antd'
function Memo() {
  console.log(" Memo render =================");
  const [a,setA] = useState({value:0})
  const [b,setB] = useState({value:0})
  const [c,setC] = useState({value:0})


  const addA = function(){
    setA({value:a.value+1})
  }
  const addB = function(){
    setB({value:b.value+1})
  }
  const addC = function(){
    setC({value:c.value+1})
  }

  const addC2 = useCallback( function(){
    setC({value:c.value+1})
  },[c])

  return (
    <>
      点击按钮，观察下面哪些子组件被更新了<br/>
      通过本例子理解 React.memo和useCallback的使用<br/>

      通过React.memo包括的子组件会根据属性的内存地址值是否变化而判断子组件是否rerender , useCallback是将函数缓存，避免重新渲染生成新的函数<br/>

      其中子组件A和子组件B只传递了数据，而组件C和组件D除了传递数据还传递了函数<br/>
      <b>useCallback一般和React.memo联合使用，用于优化组件在依赖的变量没有改变时不重新渲染组件</b><br/>
      <Divider></Divider>
      a:{a.value} <Button onClick={addA} >a++</Button> <br/> 
      点击a++ <br/>
      MemoChildA：会重新渲染，自身引用的变量a改变了 <br/>
      MemoChildB：不会重新渲染，使用了memo包裹，只依赖的变量b没变<br/>
      MemoChildC：会重新渲染，使用了memo包裹，自身引用的变量c没有变化但是引用的函数addC改变了(因为父组件重新渲染了,函数addC被重新放到内存中,内存地址变了)<br/>
      MemoChildD：不会重新渲染，使用了memo包裹，自身引用的变量c没有变化且addC2被useCallback包裹，引用的是addC2被缓存的内存地址，该内存地址没有变<br/>
      
      <Divider></Divider>
      b:{b.value} <Button onClick={addB} >b++</Button><br/> 
      点击b++ <br/>
      MemoChildA：会重新渲染，没有使用memo包裹，父组件的渲染会导致子组件的渲染，无论依赖的属性是否变化 <br/>
      MemoChildB：会重新渲染，只依赖的变量b改变了<br/>
      MemoChildC：会重新渲染，使用了memo包裹，自身引用的变量c没有变化但是引用的函数addC改变了(因为父组件重新渲染了,函数addC被重新放到内存中,内存地址变了)<br/>
      MemoChildD：不会重新渲染，使用了memo包裹，自身引用的变量c没有变化且addC2被useCallback包裹，引用的是addC2被缓存的内存地址，该内存地址没有变<br/>

      <Divider></Divider>
      c:{c.value} <Button onClick={addC} >c++</Button><br/> 
      点击c++ <br/>
      MemoChildA：会重新渲染，没有使用memo包裹，父组件的渲染会导致子组件的渲染，无论依赖的属性是否变化 <br/>
      MemoChildB：不会重新渲染，使用了memo包裹，只依赖的变量b没变<br/>
      MemoChildC：会重新渲染，使用了memo包裹，自身引用的变量c改变<br/>
      MemoChildD：会重新渲染，使用了memo包裹，自身引用的变量c改变<br/>
      <Divider></Divider>

      <MemoChildA data={a}></MemoChildA><br/>
      <MemoChildB data={b}></MemoChildB><br/>
      <MemoChildC data={c} fn={addC}></MemoChildC><br/>
      <MemoChildD data={c} fn={addC2}></MemoChildD>
    </>
  );
}




export default Memo;
